package com.chuangke.sinotrukbudget.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chuangke.admin.model.SysDept;
import com.chuangke.admin.model.SysDict;
import com.chuangke.admin.service.SysDeptService;
import com.chuangke.admin.service.SysDictService;
import com.chuangke.common.enums.OrderStatusEnum;
import com.chuangke.common.utils.DateUtils;
import com.chuangke.flow.enums.FlowNodeStatusEnum;
import com.chuangke.flow.model.FlowRuTask;
import com.chuangke.flow.sdao.FlowRuTaskService;
import com.chuangke.sinotrukbudget.manager.BudgetManager;
import com.chuangke.sinotrukbudget.model.BudgetAccount;
import com.chuangke.sinotrukbudget.model.BudgetBpcPlan;
import com.chuangke.sinotrukbudget.sdao.BudgetBpcPlanDaoService;
import com.chuangke.sinotrukbudget.service.BudgetTodoService;
import com.chuangke.sinotrukbudget.util.BudgetUtil;

@Service
public class BudgetTodoServiceImpl implements BudgetTodoService {

	@Autowired
	private BudgetBpcPlanDaoService budgetBpcPlanDaoService;

	@Autowired
	private SysDeptService sysDeptService;
	@Autowired
	private SysDictService sysDictService;
	@Autowired
	private FlowRuTaskService flowRuTaskService;
	@Autowired
	private BudgetManager budgetManager;

	@Override
	public Map<String, Object> getTodoCount(String userId, List<String> userDeptList) {
		Map<String, Object> result = new HashMap<>();
		result.put("need_edit_budget_task_count", getNeededEditBudgetTaskCount(userDeptList));
		result.put("todo_audit_budget_task_count", getTodoAuditBudgetTaskCount(userId));
		result.put("done_audit_budget_task_count", getDoneAuditBudgetTaskCount(userId));
		result.put("done_over_audit_budget_task_count", getDoneAndOverAuditBudgetTaskCount(userId));
		result.put("reject_audit_budget_task_count", getRejectAuditBudgetTaskCount(userId));
		return result;
	}

	/**
	 * 获取待修改预算量
	 *
	 * @param userDeptList
	 * @return
	 */
	private long getNeededEditBudgetTaskCount(List<String> userDeptList) {
		if (CollectionUtils.isEmpty(userDeptList)) {
			return 0;
		}

		List<String> accountIdList = budgetManager.getGuikoukm();

		QueryWrapper<BudgetBpcPlan> qw = new QueryWrapper<>();
		qw.select("distinct t_category,t_entity,t_account,handle_time");// count(distinct t_category,t_entity,t_account)
																		// count
		qw.lambda().eq(BudgetBpcPlan::getStatus, OrderStatusEnum.EDIT.getCode())
				.eq(BudgetBpcPlan::getAccountType, BudgetAccount.ACCOUNT_TYPE_CW)
				.in(BudgetBpcPlan::gettEntity, userDeptList);
		if (!CollectionUtils.isEmpty(accountIdList)) {
			qw.lambda().in(BudgetBpcPlan::gettAccount, accountIdList);
		}
		BudgetUtil.appendRestrictQueryWrapperAudit(qw);
		return budgetBpcPlanDaoService.count(qw);
	}

	/**
	 * 获取待修改预算统计
	 *
	 * @param userDeptList
	 * @return
	 */
	@Override
	public List<Map<String, Object>> getNeededEditBudgetTask(List<String> userDeptList) {
		if (CollectionUtils.isEmpty(userDeptList)) {
			return new ArrayList<>();
		}

		List<String> accountIdList = budgetManager.getGuikoukm();

		QueryWrapper<BudgetBpcPlan> qw = new QueryWrapper<>();
		qw.select("distinct t_category,t_entity,handle_time t_time,count(distinct t_account) count")
				.groupBy("t_category,t_entity,handle_time");
		qw.lambda().eq(BudgetBpcPlan::getStatus, OrderStatusEnum.EDIT.getCode())
				.eq(BudgetBpcPlan::getAccountType, BudgetAccount.ACCOUNT_TYPE_CW)
				.in(BudgetBpcPlan::gettEntity, userDeptList);
		if (!CollectionUtils.isEmpty(accountIdList)) {
			qw.lambda().in(BudgetBpcPlan::gettAccount, accountIdList);
		}
		BudgetUtil.appendRestrictQueryWrapperAudit(qw);
		List<Map<String, Object>> list = budgetBpcPlanDaoService.listMaps(qw);

		return handleData(list);
	}

	/**
	 * 获取审批待办任务量
	 *
	 * @param userId
	 * @return
	 */
	public long getTodoAuditBudgetTaskCount(String userId) {
		String insql = "SELECT order_id FROM flow_ru_task WHERE status='" + FlowNodeStatusEnum.unhandle.getCode()
				+ "' and user_id='" + userId + "'";

		QueryWrapper<BudgetBpcPlan> qw = new QueryWrapper<>();
		qw.select("distinct t_category,t_entity,t_account,handle_time");
		qw.lambda().inSql(BudgetBpcPlan::getId, insql).eq(BudgetBpcPlan::getAccountType, BudgetAccount.ACCOUNT_TYPE_CW);
		qw.lambda().eq(BudgetBpcPlan::getStatus, OrderStatusEnum.APPROVAL.getCode());
		BudgetUtil.appendRestrictQueryWrapperAudit(qw);
		return budgetBpcPlanDaoService.count(qw);
	}

	public List<String> getTodoUser() {
		QueryWrapper<FlowRuTask> qw = new QueryWrapper<>();
		qw.select("distinct user_id");
		qw.lambda().eq(FlowRuTask::getStatus, FlowNodeStatusEnum.unhandle.getCode());
		List<FlowRuTask> list = flowRuTaskService.list(qw);
		return list.stream().map(FlowRuTask::getUserId).filter(user -> !StrUtil.isBlank(user))
				.collect(Collectors.toList());
	}

	public List<String> getTodoUser(List<String> orderIdList) {
		QueryWrapper<FlowRuTask> qw = new QueryWrapper<>();
		qw.select("distinct user_id");
		qw.lambda().eq(FlowRuTask::getStatus, FlowNodeStatusEnum.unhandle.getCode());
		qw.lambda().in(FlowRuTask::getOrderId, orderIdList);

		List<FlowRuTask> list = flowRuTaskService.list(qw);
		return list.stream().map(FlowRuTask::getUserId).filter(user -> !StrUtil.isBlank(user))
				.collect(Collectors.toList());
	}

	/**
	 * 获取审批待办任务统计
	 *
	 * @param userDeptList
	 * @return
	 */
	@Override
	public List<Map<String, Object>> getTodoAuditBudgetTask(String userId) {
		String insql = "SELECT order_id FROM flow_ru_task WHERE status='" + FlowNodeStatusEnum.unhandle.getCode()
				+ "' and user_id='" + userId + "'";

		QueryWrapper<BudgetBpcPlan> qw = new QueryWrapper<>();
		qw.select("distinct t_category,t_entity,handle_time t_time,count(distinct t_account) count")
				.groupBy("t_category,t_entity,handle_time");
		qw.lambda().inSql(BudgetBpcPlan::getId, insql);
		qw.lambda().eq(BudgetBpcPlan::getStatus, OrderStatusEnum.APPROVAL.getCode()).eq(BudgetBpcPlan::getAccountType,
				BudgetAccount.ACCOUNT_TYPE_CW);
		BudgetUtil.appendRestrictQueryWrapperAudit(qw);

		List<Map<String, Object>> list = budgetBpcPlanDaoService.listMaps(qw);

		return handleData(list);
	}

	/**
	 * 获取已办任务量
	 *
	 * @param userDeptList
	 * @return
	 */
	private long getDoneAuditBudgetTaskCount(String userId) {
		String insql = "SELECT order_id FROM flow_hi_task_log WHERE status='" + FlowNodeStatusEnum.agree.getCode()
				+ "' and user_id='" + userId + "'";

		QueryWrapper<BudgetBpcPlan> qw = new QueryWrapper<>();
		qw.select("distinct t_category,t_entity,t_account,handle_time");
		qw.lambda().inSql(BudgetBpcPlan::getId, insql).eq(BudgetBpcPlan::getAccountType, BudgetAccount.ACCOUNT_TYPE_CW);
		BudgetUtil.appendRestrictQueryWrapperAudit(qw);
		return budgetBpcPlanDaoService.count(qw);
	}

	/**
	 * 获取已办任务量
	 *
	 * @param userDeptList
	 * @return
	 */
	@Override
	public List<Map<String, Object>> getDoneAuditBudgetTask(String userId) {
		String insql = "SELECT order_id FROM flow_hi_task_log WHERE status='" + FlowNodeStatusEnum.agree.getCode()
				+ "' and user_id='" + userId + "'";

		QueryWrapper<BudgetBpcPlan> qw = new QueryWrapper<>();
		qw.select("distinct t_category,t_entity,handle_time t_time,count(distinct t_account) count")
				.groupBy("t_category,t_entity,handle_time");
		qw.lambda().inSql(BudgetBpcPlan::getId, insql).eq(BudgetBpcPlan::getAccountType, BudgetAccount.ACCOUNT_TYPE_CW);
		BudgetUtil.appendRestrictQueryWrapperAudit(qw);
		List<Map<String, Object>> list = budgetBpcPlanDaoService.listMaps(qw);

		return handleData(list);
	}

	/**
	 * 获取已办结任务量
	 *
	 * @param userDeptList
	 * @return
	 */
	private long getDoneAndOverAuditBudgetTaskCount(String userId) {
		String insql = "SELECT order_id FROM flow_hi_task_log WHERE status='" + FlowNodeStatusEnum.agree.getCode()
				+ "' and user_id='" + userId + "'";

		QueryWrapper<BudgetBpcPlan> qw = new QueryWrapper<>();
		qw.select("distinct t_category,t_entity,t_account,handle_time");
		qw.lambda().eq(BudgetBpcPlan::getStatus, OrderStatusEnum.COMPLETE.getCode());
		qw.lambda().inSql(BudgetBpcPlan::getId, insql).eq(BudgetBpcPlan::getAccountType, BudgetAccount.ACCOUNT_TYPE_CW);
		BudgetUtil.appendRestrictQueryWrapperAudit(qw);
		return budgetBpcPlanDaoService.count(qw);
	}

	/**
	 * 获取已办结任务统计
	 *
	 * @param userDeptList
	 * @return
	 */
	@Override
	public List<Map<String, Object>> getDoneAndOverAuditBudgetTask(String userId) {
		String insql = "SELECT order_id FROM flow_hi_task_log WHERE status='" + FlowNodeStatusEnum.agree.getCode()
				+ "' and user_id='" + userId + "'";

		QueryWrapper<BudgetBpcPlan> qw = new QueryWrapper<>();
		qw.select("distinct t_category,t_entity,handle_time t_time,count(distinct t_account) count")
				.groupBy("t_category,t_entity,handle_time");
		qw.lambda().eq(BudgetBpcPlan::getStatus, OrderStatusEnum.COMPLETE.getCode());
		qw.lambda().inSql(BudgetBpcPlan::getId, insql).eq(BudgetBpcPlan::getAccountType, BudgetAccount.ACCOUNT_TYPE_CW);
		BudgetUtil.appendRestrictQueryWrapperAudit(qw);
		List<Map<String, Object>> list = budgetBpcPlanDaoService.listMaps(qw);

		return handleData(list);
	}

	/**
	 * 获取退回任务量
	 *
	 * @param userDeptList
	 * @return
	 */
	private long getRejectAuditBudgetTaskCount(String userId) {
		String insql = "SELECT order_id FROM flow_hi_task_log WHERE status='" + FlowNodeStatusEnum.reject.getCode()
				+ "' and user_id='" + userId + "'";

		QueryWrapper<BudgetBpcPlan> qw = new QueryWrapper<>();
		qw.select("distinct t_category,t_entity,t_account,handle_time");
		qw.lambda().inSql(BudgetBpcPlan::getId, insql).eq(BudgetBpcPlan::getAccountType, BudgetAccount.ACCOUNT_TYPE_CW);
		BudgetUtil.appendRestrictQueryWrapperAudit(qw);
		return budgetBpcPlanDaoService.count(qw);
	}

	/**
	 * 获取退回任务统计
	 *
	 * @param userDeptList
	 * @return
	 */
	@Override
	public List<Map<String, Object>> getRejectAuditBudgetTask(String userId) {
		String insql = "SELECT order_id FROM flow_hi_task_log WHERE status='" + FlowNodeStatusEnum.reject.getCode()
				+ "' and user_id='" + userId + "'";

		QueryWrapper<BudgetBpcPlan> qw = new QueryWrapper<>();
		qw.select("distinct t_category,t_entity,handle_time t_time,count(distinct t_account) count")
				.groupBy("t_category,t_entity,handle_time");
		qw.lambda().inSql(BudgetBpcPlan::getId, insql).eq(BudgetBpcPlan::getAccountType, BudgetAccount.ACCOUNT_TYPE_CW);
		BudgetUtil.appendRestrictQueryWrapperAudit(qw);
		List<Map<String, Object>> list = budgetBpcPlanDaoService.listMaps(qw);

		return handleData(list);
	}

	private List<Map<String, Object>> handleData(List<Map<String, Object>> list) {
		list = handleDataTime(list);

		Map<String, SysDict> categoryMap = sysDictService.findMap("budget_version");
		Map<String, SysDept> deptMap = sysDeptService.findMap();
		list.forEach(data -> {
			data.put("t_category_name", categoryMap.get(data.get("t_category")) == null ? ""
					: categoryMap.get(data.get("t_category")).getName());
			data.put("t_entity_name",
					deptMap.get(data.get("t_entity")) == null ? "" : deptMap.get(data.get("t_entity")).getName());
		});
		return list;
	}

	private List<Map<String, Object>> handleDataTime(List<Map<String, Object>> list) {
		Map<String, Map<String, Object>> resultMap = new HashMap<>();

		/* 典型车型的time列表 */
		List<String> budTimeList = list.stream()
				.filter(todo -> todo.get("t_category").toString().startsWith("BUD")
						&& !todo.get("t_time").toString().endsWith("INP"))
				.map(todo -> (String) todo.get("t_time")).distinct().collect(Collectors.toList());

		for (Map<String, Object> data : list) {
			String entity = (String) data.get("t_entity");
			String category = (String) data.get("t_category");
			String time = (String) data.get("t_time");
			time = getConditionTime(entity, category, time, budTimeList);

			data.put("t_time", time);

			String key = String.format("%s-%s-%s", entity, category, time);

			if (resultMap.keySet().contains(key)) {
				Map<String, Object> newData = resultMap.get(key);
//				newData.put("count", ((BigDecimal)newData.get("count")).add((BigDecimal)data.get("count"))) ;
				new BigDecimal(data.get("count").toString());
				newData.put("count", (new BigDecimal(newData.get("count").toString()))
						.add(new BigDecimal(data.get("count").toString())));
			} else {
				resultMap.put(key, data);
			}
		}

		return new ArrayList<>(resultMap.values());
	}

	/**
	 * 典型车型的时间要特殊处理一下
	 *
	 * @param entity
	 * @param category
	 * @param time
	 * @param budTimeList
	 * @return
	 */
	private String getConditionTime(String entity, String category, String time, List<String> budTimeList) {
		if (!category.startsWith("BUD")) {
			return time;
		}
		// 不以INP结尾说明是本年的预算，本年预算是一个月份，直接返回
		if (!time.endsWith("INP")) {
			return time;
		}

		String lastYear = DateUtils.previousYear(time.split("\\.")[0]);
		List<String> tList = budTimeList.stream().filter(t -> lastYear.equals(t.split("\\.")[0]))
				.collect(Collectors.toList());
		if (!CollectionUtils.isEmpty(tList)) {
			return tList.get(0);
		}

		QueryWrapper<BudgetBpcPlan> qw = new QueryWrapper<>();
		qw.select("distinct t_time");
		qw.lambda().eq(BudgetBpcPlan::gettCategory, category);// .eq(BudgetBpcPlan::gettEntity, entity);
		qw.lambda().like(BudgetBpcPlan::gettTime, lastYear);
		List<BudgetBpcPlan> bbpList = budgetBpcPlanDaoService.list(qw);
		if (!CollectionUtils.isEmpty(bbpList)) {
			time = bbpList.get(0).gettTime();
		}

		return time;
	}

}
